package com.project.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cfg.service.CfgCategoryService;
import com.common.api.ApprovalApi;
import com.common.core.domain.AjaxResult;
import com.common.core.domain.entity.SysUser;
import com.common.core.domain.model.LoginUser;
import com.common.utils.CurrentRoleUtils;
import com.common.utils.QueryWrapperUtils;
import com.common.utils.SecurityUtils;
import com.common.utils.StringUtils;
import com.common.utils.bean.BizProcessMessages;
import com.common.utils.bean.ReflectionUtils;
import com.common.utils.uuid.IdUtils;
import com.flowable.domain.vo.task.BpmTaskApproveReqVO;
import com.flowable.service.IFlowTaskService;
import com.project.domain.bo.MiddleCheckOrCompleteBo;
import com.project.domain.entity.BizProjectComplete;
import com.project.domain.entity.BizYfContract;
import com.project.domain.entity.xjProject.BizXjProject;
import com.project.domain.entity.zxProject.BizZxProject;
import com.project.domain.vo.BizProjectCompleteVo;
import com.project.domain.vo.NavigationForProVo;
import com.project.mapper.BizProjectMiddleCheckMapper;
import com.project.mapper.CompleteProMapper;
import com.project.service.ICompleteProService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

@Service("biz_project_complete")
public class CompleteProServiceImpl implements ICompleteProService {

    @Autowired
    private CompleteProMapper completeProMapper;

    @Autowired
    CfgCategoryService cfgCategoryService ;

    @Autowired
    ProjectMiddleCheckServiceImpl middleCheckService;

    @Autowired
    private BizProjectMiddleCheckMapper bizProjectMiddleCheckMapper;

    @Autowired
    ProjectInitServiceImpl projectInitService;


    //发起流程
    @Autowired
    private ApprovalApi approvalApi;

    //流程引擎
    @Autowired
    private IFlowTaskService flowTaskService;

    @Autowired
    private ProCheckCommon checkCommon;

    /**
     * 左上角根据状态的数量统计
     * @param bizProjectComplete
     * @return
     */
    public List<NavigationForProVo.NameAndCount> selectGroups(MiddleCheckOrCompleteBo bizProjectComplete){
        List<NavigationForProVo.NameAndCount> res = new ArrayList<>();
        try{
            QueryWrapper<NavigationForProVo.NameAndCount> queryWrapper = new QueryWrapper<>();
            queryWrapper = this.getCondition(queryWrapper,bizProjectComplete,"group");//拼条件
            QueryWrapperUtils.getParamsProBusiness(queryWrapper,SecurityUtils.getLoginUser().getUser());//用户权限

            res = completeProMapper.selectGroups(queryWrapper,bizProjectComplete);
        }catch (Exception exception){
            res = null;
        }
        return res;
    }

    /**
     * 查询项目结项
     *
     * @param ID 项目结项主键
     * @return 项目结项
     */
    @Override
    public BizProjectComplete selectBizProjectCompleteByID(String ID)
    {
        try{
            return completeProMapper.selectDetail(ID);
        }catch (Exception exception){
            return new BizProjectComplete();
        }
    }

    /**
     * 查询项目结项列表
     * @param bizProjectComplete 项目结项
     * @param type
     * @return 项目结项
     */
    @Override
    public IPage<BizProjectCompleteVo> selectBizProjectCompleteList(MiddleCheckOrCompleteBo bizProjectComplete, String type)
    {
        IPage<BizProjectCompleteVo> res = new Page<>();
        try{
            String setAcceptTypeCategoryId = cfgCategoryService.getCategoryIdByType("验收类别");//获取验收类别的配置id
            QueryWrapper<BizProjectCompleteVo> queryWrapper = new QueryWrapper<>();
            queryWrapper = this.getCondition(queryWrapper,bizProjectComplete,"list");//拼条件
            QueryWrapperUtils.getParamsProBusiness(queryWrapper,SecurityUtils.getLoginUser().getUser());//用户权限

            //处理排序字段
            String orderStr = StringUtils.isNotBlank(bizProjectComplete.getOrderStr())?bizProjectComplete.getOrderStr():"createdate";
            String orderType = StringUtils.isNotBlank(bizProjectComplete.getOrderType())?bizProjectComplete.getOrderType():"desc";
//            bizProjectComplete.setOrderStr(projectInitService.changeStringToUp(orderStr));
            bizProjectComplete.setOrderStr(orderStr);
            bizProjectComplete.setOrderType(orderType);

            if(type.equals("select")){
                IPage<BizProjectCompleteVo> myPage = new Page<>(bizProjectComplete.getPageNo(), bizProjectComplete.getPageSize());
                res = completeProMapper.selectListInfos(myPage,queryWrapper,bizProjectComplete,setAcceptTypeCategoryId);
                res = middleCheckService.getCheckInfosForList(res,"项目结项",BizProjectCompleteVo::setTaskId,BizProjectCompleteVo::setIsAuditor,BizProjectCompleteVo::getProcessInstanceId);
            }else{
                IPage<BizProjectCompleteVo> myPage = new Page<>(1, 1000);
                res = completeProMapper.selectListInfosForExport(myPage,queryWrapper,bizProjectComplete,setAcceptTypeCategoryId);
            }
        }catch (Exception exception){
            String ex = exception.getMessage();
        }

        return res;
    }

    /**
     * 拼条件
     * @param queryWrapper
     * @param bizProjectComplete
     * @return
     */
    private QueryWrapper getCondition(QueryWrapper queryWrapper,MiddleCheckOrCompleteBo bizProjectComplete,String funcType){
        try{
            bizProjectComplete.setProjectTypeCode(addQuotationToStr(bizProjectComplete.getProjectTypeCode()));//处理项目分类id
            bizProjectComplete.setUnitId(addQuotationToStr(bizProjectComplete.getUnitId()));//处理所属单位id
            bizProjectComplete.setCheckstatus(addQuotationToStr(bizProjectComplete.getCheckstatus()));//处理审核状态id
            bizProjectComplete.setAcceptanceType(addQuotationToStr(bizProjectComplete.getAcceptanceType()));//处理验收id

            //处理结项日期字段（年份4、年月7、年月日）
            String startAcceptTime = changeDateString(bizProjectComplete.getStartTime(),"start");
            String endAcceptTime = changeDateString(bizProjectComplete.getEndTime(),"end");

            queryWrapper.eq(StringUtils.isNotBlank(bizProjectComplete.getProClass()), "zb.PROJECT_CLASS", bizProjectComplete.getProClass())
                    .ge(StringUtils.isNotBlank(startAcceptTime), "COMPLETE_DATE", startAcceptTime)
                    .le(StringUtils.isNotBlank(endAcceptTime), "COMPLETE_DATE", endAcceptTime);
            if(funcType.equals("list")){
                queryWrapper.eq(StringUtils.isNotBlank(bizProjectComplete.getCheckstatusByGroup()), "zb.CHECKSTATUS", bizProjectComplete.getCheckstatusByGroup());
            }

            return queryWrapper;
        }catch (Exception exception){
            return queryWrapper;
        }
    }

    /**
     * 保存项目结项（审核逻辑处理）
     * @param bizProjectComplete 项目结项
     * @param operateType 操作类型
     * @return 结果
     */
    @Override
    public AjaxResult saveBizProjectComplete(BizProjectComplete bizProjectComplete, String operateType)
    {
        String completeId = "";
        LoginUser loginUser = SecurityUtils.getLoginUser();
        String currentRoleKey = CurrentRoleUtils.getCurrentRoleKey(); //当前角色
        Integer submitType = bizProjectComplete.getSubmitType() == null?-1:bizProjectComplete.getSubmitType();
        String processInstanceId = "";
        String checkStatus = bizProjectComplete.getCheckstatus();
        switch (submitType){
            case -1:{
                //暂存：新建编辑都只保存信息，不做任何其他操作
                if(!currentRoleKey.equals("biz_kyms") && !currentRoleKey.equals("biz_kycgly") || !StringUtils.isNotBlank(checkStatus)){
                    bizProjectComplete.setCheckstatus("-1");//科研管理员、秘书的暂存都不改状态
                }
                completeId = this.saveCompleteInfos(bizProjectComplete,operateType);
                return StringUtils.isNotBlank(completeId)?completeId.contains("失败")?AjaxResult.error(completeId):AjaxResult.success(BizProcessMessages.SAVE_SUCCESS):AjaxResult.error(BizProcessMessages.SAVE_FAIL);
            }
            case 1:{
                //提交（科研人员）：新建编辑均保存信息+发起流程
                bizProjectComplete.setCheckstatus("1");
                bizProjectComplete = ReflectionUtils.updateFields(bizProjectComplete, BizProjectComplete.class);
                completeId = this.saveCompleteInfos(bizProjectComplete,operateType);
                if(StringUtils.isNotBlank(completeId)){
                    if(completeId.contains("失败")){
                        return AjaxResult.error(completeId);
                    }else{
                        processInstanceId = approvalApi.businessEntryApproval(completeId, "项目结项");//发起流程并返回示例id
                        //保存成功但流程实例id为空 -> 发起流程失败
                        return !StringUtils.isNotBlank(processInstanceId)?AjaxResult.warn(BizProcessMessages.SAVE_PARTIAL_SUCCESS):AjaxResult.success(BizProcessMessages.SAVE_SUCCESS);
                    }
                }else{
                    return AjaxResult.error(BizProcessMessages.SAVE_FAIL);
                }
            }
            case 2:{
                //保存并通过（管理员）：审核中且是当前审核人-》调流程接口；直接通过-》实例id为0
                if(operateType.equals("add") || operateType.equals("edit") && (!StringUtils.isNotBlank(checkStatus) || StringUtils.isNotBlank(checkStatus)&&!checkStatus.equals("1"))){
                    //审核状态是暂存*不通过 -》直接将实例id置为0
                    bizProjectComplete = ReflectionUtils.updateFields(bizProjectComplete, BizProjectComplete.class);
                    bizProjectComplete.setProcessInstanceId("0");
                    bizProjectComplete.setCheckstatus("2");
                    completeId = this.saveCompleteInfos(bizProjectComplete,operateType);
                    if(StringUtils.isNotBlank(completeId)){
                        if(completeId.contains("失败")){
                            return AjaxResult.error(completeId);
                        }else{
                            //通过要调完成审核后的业务
                            this.updateBusinessStatus("biz_project_complete",completeId,"2",loginUser.getUser().getUserRealId());
                            return AjaxResult.success(BizProcessMessages.SAVE_SUCCESS);
                        }
                    }else{
                        return AjaxResult.error(BizProcessMessages.SAVE_FAIL);
                    }
                }else{
                    //审核状态为审核中且是当前审核人（审核人逻辑前端处理）：保存并调流程接口
                    try{
                        completeId = this.saveCompleteInfos(bizProjectComplete,operateType);
                        if(StringUtils.isNotBlank(completeId)){
                            if(completeId.contains("失败")){
                                return AjaxResult.error(completeId);
                            }
                            else{
                                BpmTaskApproveReqVO bta = new BpmTaskApproveReqVO();
                                bta.setId(bizProjectComplete.getTaskId());
                                bta.setReason(SecurityUtils.getNickName() + "保存并通过");
                                flowTaskService.approveTask(SecurityUtils.getUserId(), bta);
                                return AjaxResult.success(BizProcessMessages.SAVE_SUCCESS);
                            }
                        }else{
                            return AjaxResult.error(BizProcessMessages.SAVE_FAIL);
                        }
                    }catch (Exception exception){
                        return AjaxResult.warn(BizProcessMessages.SAVE_SUCCESS_APPROVE_FAIL);
                    }
                }
            }
            default: return AjaxResult.error(BizProcessMessages.SAVE_FAIL);
        }
    }

    /**
     * 保存中结项信息（业务）
     * @param bizProjectComplete
     * @param operateType
     * @return
     */
    private String saveCompleteInfos(BizProjectComplete bizProjectComplete, String operateType){
        String res = "";
        int operRes = 0;
        SysUser loginUser = SecurityUtils.getLoginUser().getUser();
        Date date = new Date();
        SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        try{
            //判断结项时间格式
            String completeDate = bizProjectComplete.getCompleteDate();
            if(StringUtils.isNotBlank(completeDate)){
                if(middleCheckService.isValidTimeFormat(completeDate,"yyyy-MM-dd") && middleCheckService.isValidTimeFormat(completeDate,"yyyy-MM-dd  HH:mm:ss")){
                    return "保存失败，时间格式错误！";
                }else{
                    bizProjectComplete.setCompleteDate(completeDate + " 00:00:00");
                }
            }else{
                bizProjectComplete.setCompleteDate(null);
            }

            bizProjectComplete.setLasteditdate(dateFormat.parse(dateFormat.format(date)));
            bizProjectComplete.setLasteditusername(loginUser.getNickName());
            bizProjectComplete.setLastedituserid(loginUser.getUserRealId());
            if(operateType.equals("add")){
                bizProjectComplete.setID(IdUtils.simpleUUID());
                bizProjectComplete.setCreatedate(dateFormat.parse(dateFormat.format(date)));
                bizProjectComplete.setCreateuserid(loginUser.getUserRealId());
                bizProjectComplete.setCreateusername(loginUser.getNickName());
                operRes = completeProMapper.insert(bizProjectComplete);
            }else{
                operRes = completeProMapper.updateById(bizProjectComplete);
            }

            if(operRes > 0){
                res = bizProjectComplete.getID();
            }
        }catch (Exception exception){
            String ex = exception.getMessage();
        }

        return res;
    }

    /**
     * 批量删除项目结项
     *
     * @param IDs 需要删除的项目结项主键
     * @return 结果
     */
    @Override
    public int deleteBizProjectCompleteByIDs(String[] IDs)
    {
        return completeProMapper.deleteBatchIds(Arrays.asList(IDs));
    }

    /**
     * 删除项目结项信息
     *
     * @param ID 项目结项主键
     * @return 结果
     */
    @Override
    public int deleteBizProjectCompleteByID(String ID)
    {
        return completeProMapper.deleteById(ID);
    }


    /**
     * 给字符串加引号
     * @param oldStr
     * @return
     */
    public String addQuotationToStr(String oldStr){
        if(StringUtils.isNotBlank(oldStr)){
            String newStr = oldStr.replace(",","','");
            return newStr ;
        }else{
            return oldStr;
        }
    }

    /**
     * 处理其他时间字符串
     * @param dateStr
     * @param startOrEnd
     * @return
     */
    public String changeDateString(String dateStr,String startOrEnd){
        if(StringUtils.isNotBlank(dateStr)){
            int strLength = dateStr.length();
            if(startOrEnd.equals("start")){
                if(strLength == 4){
                    dateStr = dateStr + "-01-01 00:00:00";
                }else if(strLength == 7){
                    dateStr = dateStr + "-01 00:00:00";
                }if(strLength == 10){
                    dateStr = dateStr + " 00:00:00";
                }
            }else{
                if(strLength == 4){
                    dateStr = dateStr + "-12-31 23:59:59";
                }else if(strLength == 7){
                    dateStr += "-01"; // 默认到每月的第一天
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                    LocalDate date = LocalDate.parse(dateStr, formatter);
                    LocalDate lastDayOfMonth = date.withDayOfMonth(date.lengthOfMonth());
                    DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                    dateStr = lastDayOfMonth.format(outputFormatter) + " 23:59:59";
                }else if(strLength == 10){
                    dateStr = dateStr + " 23:59:59";
                }
            }
        }
        return dateStr;
    }

    /**
     * 结项申请审核通过后对应的项目表项目状态置为 完成
     * @param tableName
     * @param businessId
     * @param checkStatus
     * @param sysUserId
     */
    @Override
    public void updateBusinessStatus(String tableName, String businessId, String checkStatus, String sysUserId) {
        try{
            if ("2".equals(checkStatus)){
                BizProjectComplete projectComplete = this.selectBizProjectCompleteByID(businessId);
                if(projectComplete != null){
                    String proId = projectComplete.getProjectId();
                    String proClass = projectComplete.getProjectClass();
                    if(proClass.equals("xJProject")){
                        BizXjProject xjProject = new BizXjProject();
                        xjProject.setProjectStatusId("1");
                        xjProject.setActualEndDate(projectComplete.getCompleteDate());
                        xjProject.setId(proId);
                        checkCommon.updatZB(xjProject);
                    }else if(proClass.equals("zXProject")){
                        BizZxProject zxProject = new BizZxProject();
                        zxProject.setProjectStatusId("1");
                        zxProject.setActualEndDate(projectComplete.getCompleteDate());
                        zxProject.setId(proId);
                        checkCommon.updatZB(zxProject);
                    }else{
                        BizYfContract yfContract = new BizYfContract();
                        yfContract.setId(proId);
                        yfContract.setProjectStatusId("1");

                        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
                        yfContract.setActualEndDate(dateFormat.parse(projectComplete.getCompleteDate()));
                        checkCommon.updatZB(yfContract);
                    }
                }
            }
        }catch (Exception exception){
            String ex = exception.getMessage();
        }
    }
}
